#include<iostream>
#include<cstring>
#include<unistd.h>

#include<sys/types.h>
#include<sys/socket.h>

#include"Lock.hpp"
#include"InetAddr.hpp"
#include"Log.hpp"
#include"Protocol.hpp"


using namespace LockModule;
using namespace LogMoudle;
using namespace InetAddrMoudle;

#define CONV(n) (sockaddr*)(n)

int main(int argc , char* argv[])
{
    if(argc!=3)
    {
        LOG(Logevel::INFO)<<"argc is error......";
        return 1;
    }
    //创建套接字，填写接口信息
    uint16_t port=std::stoi(argv[2]);
    std::string server_ip=argv[1];

    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd<0)
    {
        LOG(Logevel::INFO)<<"socket create error....";
        exit(1);
    }

    LOG(Logevel::INFO)<<"socket create success....";

    sockaddr_in addr;
    memset(&addr,0,sizeof(addr));
    addr.sin_addr.s_addr=inet_addr(server_ip.c_str());
    addr.sin_port=htons(port);
    addr.sin_family=AF_INET;

    //利用connect建立连接
    int n=::connect(sockfd,CONV(&addr),sizeof(addr));
    if(n<0)
    {
        LOG(Logevel::INFO)<<"connect is error";
        exit(1);
    }

    //确保请求的前后一致性，不能放到里面
    std::string message;
    while(true)
    {
        int x,y;
        char oper;
        std::cout<<"please input x: ";
        std::cin>>x;
        std::cout<<"please input y: ";
        std::cin>>y;
        std::cout<<"please input oper: ";
        std::cin>>oper;

        //创建请求
        Request req(x,y,oper);

        //序列化
        req.Serialize(message);
       
        //添加相应的报文长度
        Encode(message);
        
        //发送
        char inbuffer[1024];
        n=send(sockfd,message.c_str(),message.size(),0);
        if(n>0)
        {
            std::cout<<"信息发送成功"<<std::endl;

            //获取应答
            int m=recv(sockfd,inbuffer,sizeof(inbuffer),0);
            
            if(m>0)
            {
                //将相应的应答进行处理
                inbuffer[m]=0;
                std::string package=inbuffer;
                std::string content;

                //去除报文长度报头
                Decode(package,&content);

                //反序列化
                Response resp;
                resp.Deserialize(content);
                
                //得到结构化数据
                std::cout<<resp.Result()<<" ["<<resp.Code()<<"] "<<std::endl;
            }
            else
            {
                break;
            }
        }
        
    }
    ::close(sockfd);
    return 0;
}